package com.tansun.rule.utils;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.util.FileCopyUtils;

import com.alibaba.fastjson.JSON;
import com.tansun.rule.config.AppConfiguration;
import com.tansun.rule.pojo.EnterPoint;
import com.tansun.rule.pojo.RuleProj;
/**
 * 获取已发布的规则项目参数信息
 *
 */
public class RuleParamsUtil {

	public static Map<String,Object> parseProjectParam(RuleProj proj) throws IOException, DocumentException{
		String file = AppConfiguration.RuleProjDeployDir+"/"+proj.getProjectName()+"/"+AppConfiguration.JarFile;
		if(!new File(file).exists()){
			return null;
		}
		Map<String,Object> result = new HashMap();
		result.put("projectKey", proj.getProjectName());
		result.put("projectName", proj.getProjectZhName());
		//每个规则流对应规则集合
		Map<String,Set<String>> ruleGroup = new HashMap();
		//每个规则文件包含的参数
		Map<String,Set<String>> ruleParams = new HashMap();
		parseEnters(file, ruleGroup, ruleParams);
		/*if (!AppConfiguration.RuleProjMetaMap.containsKey(proj.getProjectName())) {
			String path = AppConfiguration.RuleProjDeployDir + "/" + proj.getProjectName() + "/"
					+ AppConfiguration.BomFile;
			File filemap = new File(path);
			AppConfiguration.RuleProjMetaMap.put(proj.getProjectName(),RuleBomMapXmlConvert.getMapping(filemap));
		}
		Map<String, MClass> metaMap = AppConfiguration.RuleProjMetaMap.get(proj.getProjectName());*/
		String path = AppConfiguration.RuleProjDeployDir + "/" + proj.getProjectName() + "/"
				+ AppConfiguration.BomFile;
		File filemap = new File(path);
		Map<String, MClass> metaMap = RuleBomMapXmlConvert.getMapping(filemap);
		List<Map<String,Object>> enters = new ArrayList();
		for(EnterPoint ep:proj.getEnterPointList()){
			Map<String,Object> enterMap = new HashMap();
			enterMap.put("enterName", ep.getName());
			enterMap.put("enterKey", ep.getCode());
			Set<String> rules = ruleGroup.get(ep.getRuleflowId());
			Map<String,Map<String,Object>> dataSetsMap = new HashMap();
			retriveDataSet(ruleGroup, ruleParams, rules, dataSetsMap, metaMap);
			enterMap.put("dataSets", dataSetsMap.values());
			enters.add(enterMap);
		}
		result.put("enters", enters);
		return result;
	}
	
	private static void retriveDataSet(Map<String,Set<String>> ruleGroup,Map<String,Set<String>> ruleParams,
			Set<String> rules,Map<String,Map<String,Object>> dataSetsMap,Map<String, MClass> metaMap){
		for(String rule:rules){
			//判断是否子流程
			if(ruleGroup.containsKey(rule)){
				retriveDataSet(ruleGroup, ruleParams, ruleGroup.get(rule), dataSetsMap, metaMap);
				continue;
			}
			Set<String> paramSet = ruleParams.get(rule);
			if(paramSet==null){
				continue;
			}
			for (String key : paramSet) {
				String[] ary = key.split("\\.");
				MClass mClass = metaMap.get(ary[1]);
				if(mClass==null){
					throw new RuntimeException("数据集:"+ary[1]+",不存在");
				}
				if (!dataSetsMap.containsKey(ary[1])) {
					dataSetsMap.put(ary[1], new HashMap<String, Object>());
					dataSetsMap.get(ary[1]).put("dataSetName", mClass.getChzn());
					dataSetsMap.get(ary[1]).put("dataSetKey", mClass.getName());
					dataSetsMap.get(ary[1]).put("params", new ArrayList<Map<String, String>>());
				}
				Map<String, String> param = new HashMap();
				param.put("paramName", mClass.getFieldMap().get(ary[2]).getChzn());
				param.put("paramKey", ary[2]);
				param.put("paramType", mClass.getFieldMap().get(ary[2]).getType());
				param.put("defaultValue", mClass.getFieldMap().get(ary[2]).getDefaultValue());
				param.put("paramFor", mClass.getParamType());//输入输出标示，in:输入，out:输出
				param.put("isCollections",  mClass.getFieldMap().get(ary[2]).getIsCollections());//"true","false"
				//param.put("options", mClass.getFieldMap().get(ary[2]).getDomainOpt());
				List params = (List) dataSetsMap.get(ary[1]).get("params");
				params.add(param);
			}
		}
	}
	
	private static void parseEnters(String file, Map<String, Set<String>> ruleGroup,
			Map<String, Set<String>> ruleParams) throws IOException, DocumentException {
		ZipFile zf = new ZipFile(file);
		InputStream in = new BufferedInputStream(new FileInputStream(file));
		ZipInputStream zin = new ZipInputStream(in);
		ZipEntry ze;
		try {
			while ((ze = zin.getNextEntry()) != null) {
				System.err.println("file - " + ze.getName() + " : " + ze.getSize() + " bytes");
				if (ze.getName().endsWith(".bpmn")) {
					InputStream ins = zf.getInputStream(ze);
					SAXReader saxReader = new SAXReader();
					Document document = saxReader.read(ins);
					Element root = document.getRootElement();
					Element process = root.element("process");
					String id = process.attributeValue("id");
					System.out.println("flow-id:" + id);
					if (ruleGroup.containsKey(id))
						continue;
					Set<String> rules = new HashSet();
					List<Element> elements = process.elements("businessRuleTask");
					for (Element e : elements) {
						System.out.println("group-id:" + e.attributeValue("ruleFlowGroup"));
						rules.add(e.attributeValue("ruleFlowGroup"));
					}
					elements = process.elements("callActivity");
					for (Element e : elements) {
						System.out.println("group-id:" + e.attributeValue("calledElement"));
						rules.add(e.attributeValue("calledElement"));
					}
					ruleGroup.put(id, rules);

				} else if (ze.getName().endsWith(".drl")) {
					String content = FileCopyUtils.copyToString(new InputStreamReader(zf.getInputStream(ze)));
					Pattern pattern = Pattern.compile(".*?ruleflow-group\\p{Blank}+\"((.*))\"");
					Matcher matcher = pattern.matcher(content);
					if (!matcher.find())
						continue;

					String rule = matcher.group(1);

					Set<String> params = new HashSet();
					params.addAll(matcherRuleFile(content));
					params.addAll(matcherOtherRuleFile(content));
					params.addAll(matcherRuleSetFile(content));
					params.addAll(matcherSetValue(content));
					params.addAll(matcherInsertValue(content));
					ruleParams.put(rule, params);
				}

			} 
		} finally {
			zin.close();
		}

	}
	
	/**
	 * 匹配this方法 eg.this["PersonalInfo"]["yearIncome"]
	 * 
	 * @return
	 */
	public static Set<String> matcherRuleFile(String drlStr) {
		Set<String> matcherSet = new HashSet<String>();
		String regex = "(this(\\[\\S*?(\\]\\[)?+\\])+?)";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(drlStr);

		while (matcher.find()) {
			String group = matcher.group(2);
			group = group.replaceAll("(\"\\])(\\[\")", "\\.");
			group = group.replaceAll("(\\[\")|(\"\\])", "");
			matcherSet.add("in."+group);
		}

		return matcherSet;
	}
	
	public static Set<String> matcherOtherRuleFile(String drlStr) {
		Set<String> matcherSet = new HashSet<String>();
		String reg = ".*?ruleHelper.getValue\\(.*?(\\S*),.*?(\\S*?)\\).*?";
		Pattern pattern = Pattern.compile(reg);
		Matcher matcher = pattern.matcher(drlStr);
		String group = new String();
		while (matcher.find()) {
			group = matcher.group(2);
			group = group.replaceAll("\"", "");
			matcherSet.add("in."+group);
		}
		return matcherSet;
	}
	
	public static Set<String> matcherRuleSetFile(String drlStr) {
		Set<String> matcherSet = new HashSet<String>();
		String reg = ".*?\\({2,}Map\\)\\(\\$insertMap\\.get\\((\\S*)\\){2,}\\.get\\((\\S*)\\){2,}.*?";
		Pattern pattern = Pattern.compile(reg);
		Matcher matcher = pattern.matcher(drlStr);
		String group = new String();
		while (matcher.find()) {
			group = matcher.group(1) + "." + matcher.group(2);
			group = group.replaceAll("\"|\\)", "");
			matcherSet.add("in."+group);
		}
		return matcherSet;
	}
	
	/**
	 * 匹配除了this eg.RuleHelper.setValue($insertMap, "Result.riskLevel", "4")
	 * 
	 * @return
	 */
	public static Set<String> matcherSetValue(String drlStr) {
		Set<String> matcherSet = new HashSet<String>();
		String reg = ".*?ruleHelper.setValue\\(.*?(\\S*)\\,.*?(\\S*)\\,.*?(\\S*)\\).*?";
		Pattern pattern = Pattern.compile(reg);
		Matcher matcher = pattern.matcher(drlStr);
		String group = new String();
		while (matcher.find()) {
			group = matcher.group(2);
			group = group.replaceAll("\"", "");
			matcherSet.add("out." + group);
		}
		return matcherSet;
	}
	
	/**
	 * 匹配除了this eg.RuleHelper.setValue($insertMap, "Result.riskLevel", "4")
	 * 
	 * @return
	 */
	public static Set<String> matcherInsertValue(String drlStr) {
		Set<String> matcherSet = new HashSet<String>();
		String reg = ".*?ruleHelper.insertValue\\(.*?(\\S*)\\,.*?(\\S*)\\,.*?(\\S*)\\).*?";
		Pattern pattern = Pattern.compile(reg);
		Matcher matcher = pattern.matcher(drlStr);
		String group = new String();
		while (matcher.find()) {
			group = matcher.group(2);
			group = group.replaceAll("\"", "");
			matcherSet.add("out." + group);
		}
		return matcherSet;
	}
	
	public static void main(String[] args) throws IOException, DocumentException {
		AppConfiguration.RuleProjDeployDir = "F:\\deployRule";
		AppConfiguration.RuleProjMap = DeployUtils.buildRuleProjs(AppConfiguration.RuleProjDeployDir);
		for(RuleProj proj:AppConfiguration.RuleProjMap.values()){
			
			System.out.println(JSON.toJSONString(RuleParamsUtil.parseProjectParam(proj)));
		}
		
	}
}
